package service

import (
	"errors"
	"go-admin/internal/model"
	mr "go-admin/internal/model/api/model_request"
	ms "go-admin/internal/model/api/model_response"
	"go-admin/pkg/app"
	"go-admin/pkg/errcode"
)

func (s *Service) CreateRole(param *mr.CreateRoleRequest) (string, error) {
	// 判断角色是否存在
	job, err := s.dao.GetRoleByJobNameAndJobCode(param)
	if err != nil {
		return job.Id, err
	}
	// 判断是否存在
	if job.Id != "" {
		return job.Id, errors.New("角色已存在")
	}
	tx := s.dao.Engine.Begin()
	// 添加角色
	insertId, err := s.dao.CreateRole(tx, param)
	if err != nil {
		tx.Rollback()
		return insertId, err
	}
	// 添加角色菜单
	// 添加角色绑定的菜单
	if err := s.dao.CreateRoleMenu(tx, insertId, param.MenuIds); err != nil {
		tx.Rollback()
		return insertId, err
	}

	// 根据菜单ids获取所有的接口类型
	menus, err := s.dao.GetMenuInType(tx, param.MenuIds, errcode.ATYPE)
	if err != nil {
		tx.Rollback()
		return insertId, err
	}
	if err = s.dao.CreateCasbin(tx, "p", param.RoleKey, menus); err != nil {
		tx.Rollback()
		return insertId, err
	}
	tx.Commit()
	return insertId, nil
}

func (s *Service) CountRole(param *mr.ListRoleRequest) (int, error) {
	return s.dao.CountRole(param)
}

func (s *Service) GetRoleList(param *mr.ListRoleRequest, pager *app.Pager) ([]*model.Role, error) {
	return s.dao.GetRoleList(param, pager.PageIndex, pager.PageSize)
}

func (s *Service) DeleteRoleS(ids []string) error {
	return s.dao.DeleteRoleS(ids)
}

func (s *Service) GetRoleById(id string) (*ms.RoleDetailResponse, error) {
	role, err := s.dao.GetRoleById(id)
	if err != nil {
		return nil, err
	}
	// 判断是否存在
	if role.Id == "" {
		return nil, err
	}
	// 获取角色id绑定的菜单
	roleMenuIds, err := s.dao.GetMenuIdsByRoleId(id)
	if err != nil {
		return nil, err
	}
	res := ms.ModelToDetailRoleRes(role, toList(roleMenuIds))
	return res, nil
}

func toList(roleMenus []*model.RoleMenu) []string {
	menuIds := make([]string, 0)
	for _, v := range roleMenus {
		menuIds = append(menuIds, v.MenuId)
	}
	return menuIds
}

func (s *Service) UpdateRole(param *mr.UpdateRoleRequest) error {
	// 开启事务
	tx := s.dao.Engine.Begin()
	// 更新角色
	if err := s.dao.UpdateRole(tx, param); err != nil {
		tx.Rollback()
		return err
	}
	// 删除角色绑定的菜单
	if err := s.dao.DeleteRoleMenuS(tx, param.Id); err != nil {
		tx.Rollback()
		return err
	}
	// 添加角色绑定的菜单
	if err := s.dao.CreateRoleMenu(tx, param.Id, param.MenuIds); err != nil {
		tx.Rollback()
		return err
	}
	// 根据角色id获取角色key
	role, err := s.dao.GetRoleById(param.Id)
	if err != nil {
		tx.Rollback()
		return err
	}
	// 操作casbin_rule表
	// 删除角色绑定的策略
	if err = s.dao.DeleteCasbin(tx, "p", role.RoleKey); err != nil {
		tx.Rollback()
		return err
	}

	// 根据菜单ids获取所有的接口类型
	menus, err := s.dao.GetMenuInType(tx, param.MenuIds, errcode.ATYPE)
	if err != nil {
		tx.Rollback()
		return err
	}
	// 批量插入策略
	if err = s.dao.CreateCasbin(tx, "p", role.RoleKey, menus); err != nil {
		tx.Rollback()
		return err
	}
	tx.Commit()
	return nil
}

func (s *Service) RoleListAll() ([]*model.Role, error) {
	return s.dao.RoleListAll()
}
